﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Threading;
using System.Diagnostics;
using System.Text.RegularExpressions;

using KaixinRobot;

namespace KaixinHouse
{

    public class House :Component
    {
        public const string basename = "!house";

        //////////////////////////////////////////////////////////////////////////////////////////////////////////////

        protected Collection<Room> RoomList = new Collection<Room>(); // 用户的房间
        protected Slot staySlot = null;
        protected House visitor = null;
        
        protected DateTime expiredTime = System.DateTime.Now.ToLocalTime();

        protected bool isSlave = false;
        
        //用于Account里面初始化House
        public House(Account acc) : base(acc)
        {
            this.isSlave = false;
        }
 
        //用于访问其它用户的房间
        public House(House vt, string userIdx) : base()
        {
            this.identity = new UserIdentity();
            this.identity.userIdx = userIdx;
            this.visitor = vt;
            this.isSlave = false;
        }

        //用于访问Slave的房间
        public House(UserIdentity slvid) : base()
        {
            this.identity = slvid;
            this.isSlave = true; //通过ID初始化的用户均为Slave
        }

        //执行House的逻辑
        public override bool Action()
        {
            if ((this.config.doMove != 1) && (this.config.doSlave != 1)) return false;

            if (!logon(this.identity)) return false;
            RunTime.setCurEnv(this.identity.userMail, "house");
            string content = KXWeb.House.Get_Main();

            TextParser tp = new TextParser(content);
            this.cash = TextParser.GetInteger( tp.getStrBtw("<strong style=\"font-family:Arial;font-size:12px;\" title=\"", "元\">") );
            tp.getNextStrBtw();
            this.capital = TextParser.GetInteger(tp.getNextStrBtw());
            TraceLog.PrintLn("用户现金={0}，总资产={1}；", this.cash, this.capital);

            this.findRoomList(content);
            this.findStayStatus(content);
            this.setWatchDog();

            //this.sortSlotList(null);
            //this.sortSlotList(this.RoomList[0]);

            this.procMove();
            this.procSlave();

            return base.Action();
        }

        //移动当前用户到一个房间内
        private int moveThisTo(Room room)
        {
            string fromUserID = this.identity.userIdx;
            string toUserID = room.userIdx;
            string toRoomID = room.roomIdx;

            if ((String.IsNullOrEmpty(fromUserID)) || (String.IsNullOrEmpty(toUserID)) ||
                (String.IsNullOrEmpty(toRoomID)) )
            {
                return -1;
            }

            TraceLog.Print("[{0}] move to [{1}] at (ROOM={2}) ......", fromUserID, toUserID, toRoomID);

            string retcode = KXWeb.House.Do_Stay(fromUserID, toUserID, toRoomID);

            string fuid = "", tuid = "", ret = "";
            string flag = "", cash = "", staycash = "";

            string tmp1 = (new TextParser(retcode)).getStrBtw("reset();parent.", ");");
            if (tmp1 == null) return -1;

            string tmp2 = (new TextParser(tmp1)).getStrBtw("(", "");
            if (tmp2 == null) return -1;

            string func_name = (new TextParser(tmp1)).getStrBtw("", "(");
            if (func_name == null) return -1;

            tmp2 = tmp2.Replace("'", "");
            string[] val = tmp2.Split(',');
            if (val.Length >= 4)
            {
                fuid = val[0];
                tuid = val[1];
                flag = val[2];
                cash = val[3];
            }
            if (val.Length >= 5)
            {
                staycash = val[4];
            }

            switch (TextParser.GetInteger(flag))
            {
                case 0:
                    ret = "Succ";
                    break;
                case 1:
                    ret = "Fail：非好友";
                    break;
                case 2:
                    ret = "Fail：已经成功";
                    break;
                case 3:
                    ret = "Fail：现金不足";
                    break;
                case 4:
                    ret = "Fail：房间人满";
                    break;
                case 5:
                    ret = "Fail：未满1个小时";
                    break;
                case 6:
                    ret = "Fail：非法操作";
                    break;
                case 7:
                    ret = "Fail：连续两次住同一人家里";
                    break;
                case 8:
                    ret = "Fail：网络繁忙";
                    break;
                default:
                    ret = "Fail：未知flag值";
                    break;
            }

            TraceLog.PrintLn(ret);
            TraceLog.PrintLn("Cash= {0}; Stay Cash= {1}", cash, staycash);

            //Write local variables back
            if (TextParser.GetInteger(flag) == 0)
            {
                UserMoveRecord.touch(this.identity.userIdx);
                this.updateRoomInfo(room);
            }
            return TextParser.GetInteger(flag);
        }

        //如果用户成功移动，更新内存中的数据结构
        private void updateRoomInfo(Room toRoom )
        {
            TraceLog.PrintLn("用户移动成功，更新From/To房间信息");

            //更新From Room
            if ( (this.staySlot != null)&&(this.staySlot.room != null ) )
            {
                foreach (Slot slot in this.staySlot.room.slotList )
                {
                    if (slot.accIdentity.equals(this.identity))
                    {
                        TraceLog.PrintLn("清除房间{0}.{1}的用户停留信息",this.staySlot.room.userIdx, this.staySlot.room.roomIdx);
                        slot.isUsed = false;
                        slot.accIdentity = null;
                        slot.stayMins = -1;
                        slot.dataGetTime = System.DateTime.Now.ToLocalTime();
                        this.staySlot = null;
                        break;
                    }
                }
            }

            //更新To Room
            if (toRoom != null)
            {
                foreach (Slot slot in toRoom.slotList)
                {
                    if (!slot.isUsed)
                    {
                        TraceLog.PrintLn("增加房间{0}.{1}的用户停留信息", toRoom.userIdx, toRoom.roomIdx);
                        slot.isUsed = true;
                        slot.accIdentity = this.identity;
                        slot.dataGetTime = System.DateTime.Now.ToLocalTime();
                        slot.stayMins = 1;
                        this.staySlot = slot;
                        break;
                    }
                }
            }
        }

        //用于在当前用户登陆下，访问其它用户的房间信息
        private House visitHouse(string userIdx)
        {
            House friend = null;
            if (userIdx.CompareTo(this.identity.userIdx) == 0)
            {
                friend = this;
            }
            else
            {
                friend = new House(this, userIdx);
                string content = KXWeb.House.Get_Friend(userIdx);

                string start = "<a href=\"/home/?uid=" + userIdx + "\" class=\"sl2\">";
                string end = "</a>";
                
                friend.identity.userName = (new TextParser(content)).getStrBtw(start, end);
                friend.findRoomList(content);
            }

            return friend;
        }

        //分析Content内容，得出用户状态
        protected int findStayStatus(string content)
        {

            if (this.isSlave) return 1; 
            if ((this.identity == null) || (String.IsNullOrEmpty(this.identity.userIdx))) return -1;

            this.staySlot = new Slot();

            //Get stay status
            //<span  class="c_sl ">我目前露宿街头</span>
            //<span  class="c_sl ">我目前住在自己家</span>
            //<span  class="c_sl ">他目前住在他自己家</span>
            //<span  class="c_sl ">我目前住在<a href=/~house/index.php?_lgmode=pri&fuid=511207 class='sl noline'>赵大海</a>家</span>
            string status_str;


            //取得用户当前所在位置
            //if ((status_str = Tool.GetMidString(content, "<span  class=\"c_sl \">", "</span>", pos, out newpos)) != null)
            if ((status_str = (new TextParser(content)).getStrBtw("<span  class=\"c_sl \">", "</span>")) != null)
            {
                if (status_str.IndexOf("露宿街头") >= 0)
                {
                    this.staySlot.isUsed = false;
                    this.staySlot.stayName = "[大街上]";
                    this.staySlot.stayMins = -1;
                }
                else
                {
                    this.staySlot.isUsed = true;
                }

                if (status_str.IndexOf("住在自己家") >= 0) this.staySlot.accIdentity = this.identity;
                if (status_str.IndexOf("住在他自己家") >= 0) this.staySlot.accIdentity = this.identity;
                if (status_str.IndexOf("住在她自己家") >= 0) this.staySlot.accIdentity = this.identity;
                if (this.staySlot.accIdentity.equals(this.identity)) this.staySlot.stayName = "[ 自己 ] 家";

                if (status_str.IndexOf("<a href=/~house/index.php?_lgmode=pri&fuid=") >= 0)
                {
                    //this.staySlot.accIdentity.userIdx = Tool.GetMidString(status_str, "<a href=/~house/index.php?_lgmode=pri&fuid=", " class='sl noline'>", pos, out newpos);
                    this.staySlot.accIdentity.userIdx = (new TextParser(status_str)).getStrBtw("<a href=/~house/index.php?_lgmode=pri&fuid=", " class='sl noline'>");

                    //this.staySlot.stayName = Tool.GetMidString(status_str, ">", "<", newpos, out pos);
                    this.staySlot.stayName = (new TextParser(status_str)).getStrBtw(">", "<");
                    this.staySlot.stayName = "[" + this.staySlot.stayName + "] 家";
                }
            }
            TraceLog.PrintLn("[{0}] 住在 {1}，", this.identity.userName, this.staySlot.stayName);


            //取得用户停留时间
            if (this.staySlot.isUsed == false) return 1; //对于露宿街头用户无法计算时间

            House stayFriend = this.visitHouse(this.staySlot.accIdentity.userIdx);
            foreach (Room room in stayFriend.RoomList)
            {
                foreach (Slot slot in room.slotList)
                {
                    if (!slot.isUsed) continue;
                    if (slot.accIdentity.equals(this.identity))
                    {
                        this.staySlot.stayMins = slot.stayMins;
                        this.staySlot.dataGetTime = slot.dataGetTime;
                        this.staySlot.room = room;
                    }
                }
            }
            TraceLog.PrintLn("[{0}] 住了 {1} 分钟。", this.identity.userName, this.staySlot.stayMins);

            return 1;
        }

        //根据用户过期时间调整下次启动时间
        protected void setWatchDog()
        {
            if (this.identity == null) return;
            if (this.staySlot == null) return;
            if (String.IsNullOrEmpty(this.identity.userIdx)) return;

            const int MAX_STAY_TIME = 60 * 24;
            this.expiredTime = System.DateTime.Now.ToLocalTime();

            if ((this.staySlot.isUsed) && (this.config.checkExpired == 1))
            {
                if ((this.staySlot.stayMins >= 0) || (this.staySlot.stayMins <= MAX_STAY_TIME))
                {
                    int kickOutMin = MAX_STAY_TIME - this.staySlot.stayMins;
                    TimeSpan ko_inv = new TimeSpan(0, kickOutMin, 0);
                    this.expiredTime = this.staySlot.dataGetTime + ko_inv;
                    TraceLog.PrintLn("* [{0}] 将在{1}分钟后，于{2}过期！", this.identity.userName, kickOutMin, this.expiredTime);
                    RunTime.exptRunAt(this.expiredTime);
                }
            }
        }

        //分析Content内容，得出房间列表
        protected int findRoomList(string content)
        {
            if ((this.identity == null) || (String.IsNullOrEmpty(this.identity.userIdx))) return -1;

            this.RoomList = new Collection<Room>();

            //<a href="/!house/index.php?roomid=3805"><img src="http://img.kaixin001.com.cn/i2/house/1h-2.gif"/></a>
            //<a href="/"+House.basename+"/index.php?fuid=511207&roomid=4252">
            //<a href="/"+House.basename+"/index.php?roomid=4252">
            string schstr_local = "<a href=\"/"+House.basename+"/index.php?roomid=";
            string schstr_remote = "<a href=\"/" + House.basename + "/index.php?fuid=" + this.identity.userIdx + "&roomid=";

            //<a href="/"+House.basename+"/index_room.php?roomid=5766
            //<a href="/"+House.basename+"/index_room.php?fuid=12684658&roomid=5766"
            string schstr_only1_local = "<a href=\"/" + House.basename + "/index_room.php?roomid=";
            string schstr_only1_remote = "<a href=\"/" + House.basename + "/index_room.php?fuid=" + this.identity.userIdx + "&roomid=";

            string schstr = null;
            if (content.IndexOf(schstr_local) >= 0)
            {
                schstr = schstr_local;
            }
            else if (content.IndexOf(schstr_remote) >= 0)
            {
                schstr = schstr_remote;
            }
            else if (content.IndexOf(schstr_only1_local) >= 0)
            {
                schstr = schstr_only1_local;
            }
            else if (content.IndexOf(schstr_only1_remote) >= 0)
            {
                schstr = schstr_only1_remote;
            }
            else
            {
                return -1;
            }

            string str_id = null;
            //while ((str_id = Tool.GetMidString(content, schstr, "\"", pos, out newpos)) != null)
            TextParser tp = new TextParser(content, schstr, "\"");
            while ((str_id = tp.getNextStrBtw()) != null)
            {
                //如果是奴隶，不需要获得房间的详细信息，只要有room id就可以了
                if (!this.isSlave)
                {
                    this.RoomList.Add(new Room(this, str_id));
                }
                else
                {
                    this.RoomList.Add(new Room(this.identity.userIdx, str_id));
                }
            }

            return this.RoomList.Count;
        }

        //取得当前用户的最大房间
        private Room getLargestRoom()
        {
            int maxCnt = 0;
            Room retRoom = null;
            foreach (Room room in this.RoomList)
            {
                if (this.isSlave) return room;
                if (room.totalSlots() > maxCnt)
                {
                    maxCnt = room.totalSlots();
                    retRoom = room;
                }
            }
            return retRoom;
        }

        //返回已经由时间长短排序的SlotList
        private Collection<Slot> sortSlotList( Room room )
        {
            Collection<Slot> slotList = new Collection<Slot>();

            //如果Room为空，表示对所有的Slot进行排序
            //取得所有Slot列表
            if (room == null)
            {
                foreach (Room usrRoom in this.RoomList)
                {
                    foreach (Slot slot in usrRoom.slotList)
                    {
                        if (slot.isUsed) slotList.Add(slot);
                    }
                }
            }
            else
            {
                foreach (Slot slot in room.slotList)
                {
                    if (slot.isUsed) slotList.Add(slot);
                }
            }

            //对slot进行排序
            Slot tmp = null;
            int i, j, max = slotList.Count;
            for (i = 0; i < max; i++)
                for (j = i+1; j < max; j++)
                {
                    if (slotList[i].stayMins > slotList[j].stayMins)
                    {
                        tmp = slotList[j];
                        slotList[j] = slotList[i];
                        slotList[i] = tmp;
                    }
                }

        
            //打印输出结果
            foreach (Slot slot in slotList)
            {
                if (slot.accIdentity != null)
                {
                    TraceLog.PrintLn("  - Sort Slot List: {0} @ {1} mins", slot.accIdentity.userIdx, slot.stayMins);
                }
            }
            return slotList;
        }

        //取得停留时间最短的Slave （准备踢出去）
        private UserIdentity getLatestSlave(Room room)
        {
            if (room == null) return null;
            UserIdentity minStayUser = null;
            int minStayTime = 90000;

            foreach (Slot slt in room.slotList)
            {
                if ((slt.isUsed) && (slt.stayMins < minStayTime) && (slt.stayMins > 60))
                {
                    minStayTime = slt.stayMins;
                    minStayUser = slt.accIdentity;
                }
            }

            return minStayUser;
        }

        //根据UserID取得Slave的具体信息，比如登陆信息之类
        private UserIdentity getSlaveIdentity(string userid)
        {
            if (String.IsNullOrEmpty(userid)) return null;

            foreach (UserIdentity slave in this.config.slaveList)
            {
                if (userid.Equals(slave.userIdx))
                {
                    return slave;
                }
            }
            return null;
        }

        //取得停留时间最长的Slave，用于做用户轮换
        private int getOldestSlave(out UserIdentity maxStayUser, out Room userStayRoom)
        {
            maxStayUser = null;
            userStayRoom = null;
            int maxStayTime = 0;

            foreach (Room room in this.RoomList)
            {
                foreach (Slot slt in room.slotList)
                {
                    if ((slt.isUsed) && (slt.stayMins > maxStayTime) && (slt.stayMins > 60))
                    {
                        //如果slot上面的用户不在slavelist里面，说明不是奴隶，继续
                        maxStayUser = this.getSlaveIdentity(slt.accIdentity.userIdx);
                        if (maxStayUser == null) continue;

                        maxStayTime = slt.stayMins;
                        userStayRoom = room;
                    }
                }
            }

            if (maxStayUser == null)
            {
                return 0;
            }
            else
            {
                TraceLog.PrintLn("取得最久之奴隶：{0}， 时间={1}分钟", maxStayUser.userMail, maxStayTime);
                return 1;
            }
        }

        //把停留时间最短的Slave踢出去
        private bool kickLatestUser(Room rm)
        {
            UserIdentity minStayUser = this.getLatestSlave(rm);

            if (minStayUser == null) return false;

            string toUserID = minStayUser.userIdx;
            string toRoomID = rm.roomIdx;

            if ((String.IsNullOrEmpty(toUserID)) || (String.IsNullOrEmpty(toRoomID))) return false;
            TraceLog.Print(" Drive away: [{0}] in (Room={1})", toUserID, toRoomID);

            string content = KXWeb.House.Do_KickGuest(toUserID, toRoomID);

            bool ret = content.IndexOf(",0);</script>") != -1;
            if (ret)
            {
                TraceLog.PrintLn(" Ok!");
                return true;
            }
            else
            {
                TraceLog.PrintLn(" Failed!");
                return false;
            }
        }

        protected int procMove()
        {
            int ret = -1;
            if (this.config.doMove != 1) return 0;
            if ((this.identity == null) || (this.config == null) || (this.staySlot == null)) return ret;

            //Check keep list
            bool isInKeepList = false;
            int keepUserID = 0;
            foreach (int uid in this.config.keepList)
            {
                if (TextParser.GetInteger(this.staySlot.accIdentity.userIdx) == uid)
                {
                    isInKeepList = true;
                    keepUserID = uid;
                    break;
                }
            }
            if (isInKeepList)
            {
                //主号过了23小时后会自动找房子
                if (this.staySlot.stayMins < 23 * 60)
                {
                    TraceLog.PrintLn("[{0}] 已经停留在 KeepList={1} 的朋友家里！", this.identity.userName, keepUserID);
                    return 0;
                }
                else
                {
                    TraceLog.PrintLn("[{0}] 已经停留了{1}分钟，强制移动到KeepList房子中！", this.identity.userName, this.staySlot.stayMins);
                }
            }

            //Move to stay list
            //TraceLog.PrintLn("[{0}] 不在KeepList房间里面，开始四处游荡 ......", this.accIdentity.userName);
            foreach (int uid in this.config.stayList)
            {
                if (TextParser.GetInteger(this.staySlot.accIdentity.userIdx) == uid) continue; //Skip same room

                TraceLog.PrintLn("看看朋友 StayList={0} 是否有空房间......", uid);
                House friend = this.visitHouse("" + uid);

                //主号只进入最大的房间
                ret = -1;
                Room room = friend.getLargestRoom();
                if (room == null) continue;

                //人满状况下的操作
                if (room.freeSlots() <= 0)
                {
                    //如果是自己的房间且设置踢人，则开始踢人
                    if ((friend.identity.equals(this.identity)) && (this.config.kickGuest == 1))
                    {
                        TraceLog.PrintLn("进入自己房间没有空位，准备踢人......");
                        if (!this.kickLatestUser(room)) continue;
                    }
                }

                //进入房间
                ret = this.moveThisTo(room);

                //保证未满一小时的用户能正常操作
                while ((ret == 5) && (this.config.moveWait > 0))
                {
                    TraceLog.PrintLn("等待 {0} 分钟 ......", this.config.moveWait);
                    Thread.Sleep(this.config.moveWait * 60 * 1000);
                    ret = this.moveThisTo(room);
                }

                //若未满1小时则返回
                if (ret == 5) return ret;

                //若操作成功则返回
                if (ret == 0) return ret;
            }

            return ret;
        }

        private Collection<Room> makeFreeRoomList()
        {
            Room maxRoom = this.getLargestRoom();
            Collection<Room> freeRoomList = new Collection<Room>();

            //制作空闲房间列表
            foreach (Room room in this.RoomList)
            {
                int free_slots = room.freeSlots();

                //如果主号不在本人房间内，保留最大房间的一个位置
                if ((this.staySlot == null) || (this.staySlot.room == null) || (! ( this.staySlot.room.owner.identity.equals(this.identity) )))
                {
                    if (maxRoom.roomIdx.CompareTo(room.roomIdx) == 0)
                    {
                        TraceLog.PrintLn("主号本人不在房间内，保留一个最大房间的slot");
                        free_slots--;
                    }
                }

                //如果有空闲房间的话，加入空闲房间列表
                while (free_slots > 0)
                {
                    TraceLog.PrintLn("添加空闲房间： {0}", room.roomIdx);
                    freeRoomList.Add(room);
                    free_slots--;
                }
            }
            return freeRoomList;
        }

        private Collection<UserIdentity> makeFreeSlaveList()
        {
            //制作空闲奴隶列表
            Collection<UserIdentity> freeSlaveList = new Collection<UserIdentity>();
            foreach (UserIdentity ac in this.config.slaveList)
            {
                bool foundInRoomList = false;
                foreach (Room room in this.RoomList)
                {
                    foreach (Slot slot in room.slotList)
                    {
                        if (!slot.isUsed) continue;
                        if (slot.accIdentity.equals(ac))
                        {
                            foundInRoomList = true;
                            break;
                        }
                    }
                    if (foundInRoomList) break;
                }

                if (!foundInRoomList)
                {
                    TraceLog.PrintLn("发现空闲奴隶： {0} ({1})", ac.userIdx, ac.userMail);
                    freeSlaveList.Add(ac);
                }
            }

            return freeSlaveList;
        }


        private bool moveSlaveTo(UserIdentity slave, Room room, bool moveBack)
        {
            int ret = -1;
            bool result = false;

            if (room != null)
            {
                TraceLog.PrintLn("移动奴隶 {0} 到房间 {1} ......", slave.userMail, room.roomIdx);
            }
            else
            {
                TraceLog.PrintLn("移动奴隶 {0} 到她/他自己的房间 ......", slave.userMail);
            }

            House sl = new House(slave);
            logon(slave);

            TraceLog.PrintLn("取得奴隶 [{0}] 的房间信息 ......", slave.userMail);
            string content = KXWeb.House.Get_Main();
            //sl.verifyCode = TextParser.GetVerifyCode(content);
            sl.findRoomList(content);

            //执行移动操作
            result = false;
            if (room == null)
            {
                //room = null， 表示奴隶回自己的家
                if ((sl.RoomList.Count > 0))
                {
                    //回自己家的时候没有move back
                    ret = sl.moveThisTo(sl.RoomList[0]);
                    if (ret == 0) result = true;
                }
            }
            else
            {
                if ((ret = sl.moveThisTo(room)) != 0)
                {
                    if ((ret != 5) && (sl.RoomList.Count > 0) && (moveBack))
                    {
                        TraceLog.PrintLn("奴隶返回自己房间 ......");
                        ret = sl.moveThisTo(sl.RoomList[0]);
                    }
                }
                else
                {
                    result = true;
                }
            }

            TraceLog.PrintLn("");
            return result;
        }

        private int moveFreeSlaves(Collection<Room> freeRoomList, Collection<UserIdentity> freeSlaveList)
        {
            //对FreeSlaveList进行排序
            UserMoveRecord.SortByUMR(freeSlaveList);

            //让空闲奴隶列表上的奴隶移动到空闲房间里面去
            int ret = 0, rcnt = 0, scnt = 0;
            while ((rcnt < freeRoomList.Count) && (scnt < freeSlaveList.Count))
            {
                if (RunTime.needRunAgain()) break;

                UserIdentity slave = freeSlaveList[scnt];
                Room room = freeRoomList[rcnt];

                if (this.moveSlaveTo(slave, room, true))
                {
                    rcnt++;
                }
                scnt++;
            }
            return ret;

        }

        //奴隶定期轮流值班
        private int rotateFreeSlaves(Collection<UserIdentity> freeSlaveList)
        {

            //入住最长的一个奴隶从主人房间里面挪到自己房间中去
            UserIdentity maxStaySlv = null;
            Room userStayRoom = null;
            this.getOldestSlave(out maxStaySlv, out userStayRoom);
            if ((maxStaySlv == null) || (userStayRoom == null)) return 0;

            TraceLog.PrintLn("奴隶 {0} 从主人房间挪到自己房间 ......", maxStaySlv.userMail);
            if (!this.moveSlaveTo(maxStaySlv, null, false))
            {
                return -1;
            }

            //把freeSlaveList中的奴隶顺序挪进去
            UserMoveRecord.SortByUMR(freeSlaveList);
            foreach (UserIdentity slave in freeSlaveList)
            {
                if (RunTime.needRunAgain()) break;

                if (this.moveSlaveTo(slave, userStayRoom, true))
                {
                    break;
                }
            }
            return 0;
        }

        protected int procSlave()
        {

            int ret = -1;
            if (this.config.doSlave != 1) return 0;
            if ((this.identity == null) || (this.config == null) || (this.staySlot == null)) return ret;

            RunTime.setCurEnv(this.identity.userMail, "slave");

            //制作空闲奴隶列表
            Collection<UserIdentity> freeSlaveList = this.makeFreeSlaveList(); ;
            //如果没有空闲奴隶则无法进行搬迁
            if (freeSlaveList.Count <= 0)
            {
                TraceLog.PrintLn("未发现空闲奴隶！");
                return ret;
            }


            //制作空闲房间列表
            Collection<Room> freeRoomList = this.makeFreeRoomList();
            //奴隶只在主号房间空闲的状态下才进行搬迁
            if (freeRoomList.Count <= 0)
            {
                TraceLog.PrintLn("未发现空闲房间！");
                if (this.config.rotateSlaveMove == 1)
                {
                    TraceLog.PrintLn("执行奴隶定期轮换机制 ......");
                    ret = this.rotateFreeSlaves(freeSlaveList);
                }
                return ret;
            }

            return this.moveFreeSlaves(freeRoomList, freeSlaveList);
        }


        //////////////////////////////////////////////////////////////////////////////////////////////////////////////

        //房间槽位类
        public class Slot
        {
            public bool isUsed = false;
            public UserIdentity accIdentity = new UserIdentity();
            public int stayMins = -1;
            public string stayName = null;
            public DateTime dataGetTime = System.DateTime.Now.ToLocalTime();
            public Room room = null;

            public Slot() { }
            public Slot(Room rm)
            {
                this.room = rm;
            }
        }

        //////////////////////////////////////////////////////////////////////////////////////////////////////////////

        //房间类
        public class Room
        {
            protected string roomLink = null;
            protected bool valid = false;

            public string roomIdx = null;
            public string userIdx = null;
            public House owner = null;
            public Collection<Slot> slotList = new Collection<Slot>();

            public Room(House usr, string rm_id)
            {
                this.owner = usr;
                this.roomIdx = rm_id;
                this.userIdx = usr.identity.userIdx;
                this.roomLink = "http://www.kaixin001.com/!house/index.php?fuid=" + this.userIdx + "&roomid=" + this.roomIdx;

                this.valid = this.readContent();
            }

            public Room(string user_id, string rm_id)
            {
                this.userIdx = user_id;
                this.roomIdx = rm_id;
                this.valid = false;
            }

            public bool isValid()
            {
                return this.valid;
            }

            public int totalSlots()
            {
                return this.slotList.Count;
            }

            public int usedSlots()
            {
                int count = 0;
                foreach (Slot slot in this.slotList)
                {
                    if (slot.isUsed) count++;
                }
                return count;
            }

            public int freeSlots()
            {
                int count = 0;
                foreach (Slot slot in this.slotList)
                {
                    if (!slot.isUsed) count++;
                }
                return count;
            }

            protected bool readContent()
            {
                string content = KXWeb.House.Get_Room(this.userIdx, this.roomIdx);

                //Check guest status
                //<a href='javascript:leavehouse(511207,4252)'
                //<a href='javascript:drive_away(13830164,4252)'
                //<a href='javascript:stayhouse2(511207,0,0)'
                //<a href="javascript:stayhouse(13830192,13830192,5766);"
                this.checkGuest(content, "<a href=\"javascript:stayhouse(", ");", false, 0);
                this.checkGuest(content, "<a href='javascript:leavehouse(", ")'", true, 2);
                this.checkGuest(content, "<a href='javascript:drive_away(", ")'", true, 2);
                this.checkGuest(content, "<a href='javascript:stayhouse2(", ")'", true, 3);

                TraceLog.PrintLn("ROOM-{0}: {1} Used + {2} Free = {3} Total", this.roomIdx, this.usedSlots(), this.freeSlots(), this.totalSlots());

                //TraceLog.Print("ROOM-{0}: ", this.roomIdx);
                foreach (Slot slot in this.slotList)
                {
                    string sign = "[ ]";
                    if (slot.isUsed)
                    {
                        sign = "---";
                        int uid = TextParser.GetInteger(slot.accIdentity.userIdx);
                        int stay_uid = TextParser.GetInteger(this.userIdx);
                    }
                    TraceLog.PrintLn("          {0} {1}({2}M)", sign, slot.accIdentity.userIdx, slot.stayMins);
                }
                //TraceLog.PrintLn("");

                return true;
            }

            private void checkGuest(string content, string startText, string endText, bool isIn, int param_check)
            {
                int guid = 0;
                string idText;
                TextParser tp = new TextParser(content, startText, endText);

                while ((idText = tp.getNextStrBtw()) != null)
                {
                    Slot slot = new Slot(this);

                    slot.isUsed = isIn;

                    List<int> temp = TextParser.GetIntegerList(idText);
                    if ((temp.Count == param_check) && (param_check > 0))
                    {
                        guid = temp[0];
                        if (startText.IndexOf("leavehouse") >= 0)
                        {
                            if (this.owner.visitor != null)
                            {
                                guid = TextParser.GetInteger(this.owner.visitor.identity.userIdx);
                            }
                        }
                        slot.accIdentity.userIdx = "" + guid;
                        slot.stayMins = Room.getGuestStayMins(guid, content);
                        slot.dataGetTime = System.DateTime.Now.ToLocalTime();
                    }

                    this.slotList.Add(slot);
                }
            }

            //Get a guest stay time by guest id
            private static int getGuestStayMins(int guid, string content)
            {
                //<a href="/"+House.basename+"/index.php?fuid=525328" class="sl">赵澜策</a><br>已住18小时整</div>
                string begin = "<a href=\"/"+House.basename+"/index.php?fuid=" + guid + "\" class=\"sl\">";
                string tmp = (new TextParser(content)).getStrBtw(begin, "</div>");
                if (null == tmp) return -1;

                string time = (new TextParser(tmp)).getStrBtw("已住", "");
                if (null == time) return -1;

                return (new TextParser(time)).getTotalMinutes();
            }
        }

        //////////////////////////////////////////////////////////////////////////////////////////////////////////////

    }

}
